package cn.jxau.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;



import org.apache.log4j.Logger;



/**
 * 该类定义了一些文件操作的的静态函数
 * @author licho
 *
 */
public class BaseFileRelativeUtil {
	private static final Logger log=Logger.getLogger(BaseFileRelativeUtil.class);
	/**
	 * 对文件的URL做处理,例如\\转化成/
	 * @param fileName
	 * @return
	 */
	private static String exchangeURL(String fileName){
		return fileName.replaceAll("\\\\\\\\", "/");
	}
	/**
	 * 该函数用来判断该fileName所对应的文件是否存在，如果它是一个文件，即使不存在，也会自动创建目录结构和文件名
	 * 如果它是一个目录，那么就返回false
	 * @param targetFileName
	 * @return
	 */
	private static boolean assertFileExist(String targetFileName){
		boolean flag=false;
		File file=new File(targetFileName);
		makeFile(file);//如果是文件，不存在就自动创建.如果是目录，不存在也会自动创建
		if(file.isFile()){
			flag=true;//该文件存在
		}
		return flag;
	}
	/***
	 * 判断该文件路径是否为文件,即使该路径不存在
	 * @param file
	 * @return
	 */
	private static boolean isFile(String fileName){
		boolean flag=false;
		String exeFileName=exchangeURL(fileName);
		if(exeFileName.endsWith("/")){
			exeFileName=exeFileName.substring(0, exeFileName.length()-1);
		}
		String[] files=exeFileName.split("/");
		String file=files[files.length-1];//获取最后一层目录结构来判断是否是文件
		if(file.contains(".")){
			flag=true;
		}
		return flag;
	}
	/***
	 * 将content字节数组的内容覆盖到targetfileName所代表的文件下，如果文件不存在，该方法会自动
	 * 创建文件的目录结构和文件，然后将字节写入该文件中。
	 * @param content
	 * @param targetfileName
	 * @return
	 */
	public static boolean overrideToFile(byte[] content,String targetfileName){
		boolean flag=false;
		if(!assertFileExist(targetfileName)){//断言该路径是文件而且存在
			return flag;
		}
		String exeFileName=exchangeURL(targetfileName);//对URL进行转换
		BufferedOutputStream out=null;
		try{
		out=new BufferedOutputStream(new FileOutputStream(exeFileName));
		out.write(content);
		flag=true;
		}catch(Exception e){
			log.error("写入文件时发生了错误:", e);
		}finally{
			if(out!=null){
				try{
				out.close();
				}catch(Exception e){
					log.error("文件关闭时出现异常",e);
				}
			}
		}
		return flag;
	}
	/**
	 * 将字符串以charset编码写入到targetFileName中
	 * @param content	写入的字符串
	 * @param targetFileName	目标文件路径
	 * @param charset	字符串的编码
	 * @return
	 */
	public static boolean overrideToFile(String content,String targetFileName,String charset){
		boolean flag=false;
		try {
			byte[] con=content.getBytes(charset);
			flag=overrideToFile(con, targetFileName);//写入到文件中
		} catch (UnsupportedEncodingException e) {
				log.error("字符串转码失败",e);
		}//以charset进行编码
		return flag;
	}
	/***
	 * 从指定路径读取出整个文件
	 * @param targetFileName		目标路径
	 * @return	结果的字节流
	 */
	public static byte[] readInFile(String targetFileName){
		byte[] result=null;
		String fileName=exchangeURL(targetFileName);
		log.error(fileName);
		if(!new File(fileName).exists()){
			throw new RuntimeException("你读取的文件不存在，请检查文件路径");
		}
		ByteArrayOutputStream out=new ByteArrayOutputStream();//创建一个字节输出流
		BufferedOutputStream bout=new BufferedOutputStream(out);//封装字节数组输出流
		BufferedInputStream in=null;
		try {
			in=new BufferedInputStream(new FileInputStream(fileName));
			byte[] temp=new byte[1024];
			for(int length=0;length!=-1;){
				length=in.read(temp);//尽可能的读
				if(-1==length){
					break;
				}
				bout.write(temp, 0, length);
			}
			in.close();
			bout.close();
			result=out.toByteArray();
			return result;
		} catch (Exception e) {
			log.error("读取文件时发生错误", e);
		}
		return result;
	}
	/***
	 * 以指定的编码和路径从文件中读取出字符串
	 * @param targetFileName
	 * @param charset
	 * @return
	 */
	public static String readInFile(String targetFileName,String charset){
		log.error(targetFileName);
		byte[] result=readInFile(targetFileName);
		String content=null;
		try {
			content=new String(result,charset);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return content;
	}
	/***
	 * 该函数用作创建file文件或者目录，(即使file的目录结构不存在，也能够自动创建)
	 * @param file
	 */
	public static void makeFile(File file){
		boolean isFile=isFile(file.getAbsolutePath());//获取文件的绝对路径
		log.error(file.getAbsolutePath()+"是文件嘛"+isFile);
		if(isFile){//如果是文件
			if(!file.exists()){
				File parent=file.getParentFile();
				if(!parent.exists()){
					parent.mkdirs();//创建父级目录
				}
				try {
					file.createNewFile();
				} catch (IOException e) {
					log.error("尝试创建该文件时失败",e);
				}//创建新文件
			}
		}else{
			//说明是目录
			if(!file.exists()){
				file.mkdirs();
			}
		}
	}
	/***
	 * 向该文件以charset编码进行追加内容,如果该文件不存在，那么抛出一个RuntimeException异常，提示文件不存在
	 * @param content 文件内容
	 * @param filePath	文件路径
	 * @param charset	字符编码
	 * @return
	 */
	public static boolean appendToFile(String content,String filePath,String charset){
		boolean flag=false;
		String excFilePath=exchangeURL(filePath);//对路径进行处理
		File file=new File(excFilePath);
		if(!file.exists()){
			throw new RuntimeException("该文件不存在，请检查当前路径");//不存在该文件
		}
		BufferedOutputStream out=null;
		try {
			out=new BufferedOutputStream(new FileOutputStream(file,true));//向该文件进行添加
			byte[] dataBytes=content.getBytes(charset);//以该编码进行转码字符串
			out.write(dataBytes);//向文件进行追加
			out.close();
			flag=true;
		} catch (Exception e) {
			// TODO: handle exception
			log.error("向文件追加内容时发生异常", e);
		}
		return flag;
	}
	/***
	 *该方法用作将某一个输入流copy到目标输出流
	 * @param origin	源输入流
	 * @param target	目标输出流
	 * @return	成功且没有发生异常时，返回true
	 */
	public static boolean copyStream(InputStream origin,OutputStream target){
		boolean flag=false;
		if(origin==null||target==null){
			log.error("源输入流和目标输出流不能为空");
			return flag;
		}
		BufferedOutputStream out=null;
		BufferedInputStream in=null;
		try {
			out=new BufferedOutputStream(target);
			in=new BufferedInputStream(origin);
			byte[] buffer=new byte[1024];
			for(int length=0;length!=-1;){
				length=in.read(buffer);
				if(length==-1){
					break;
				}
				out.write(buffer,0,length);
			}
			flag=true;
		} catch (Exception e) {
			log.error("copyStream发生异常", e);
		}finally{
			closeSource(in, out);
		}
		return flag;
	}
	/**
	 * 完成orginalFilePath的内容copy到targetFilePath，如果orginalFilePath不存在抛出异常,targetFilePath如果不存在会尝试
	 * 创建该文件。
	 * @param originalFilePath	源文件路径
	 * @param targetFilePath	目标文件路径
	 */
	public static void copyFile(String originalFilePath,String targetFilePath){
		File orgPath=new File(exchangeURL(originalFilePath));
		File tarPath=new File(exchangeURL(targetFilePath));
		if(!orgPath.exists()){
			throw new RuntimeException("源文件不存在");
		}else if(!tarPath.exists()){
			makeFile(tarPath);//目标文件路径不存在那么就尝试创建
		}
		try {
			copyStream(new FileInputStream(orgPath), new FileOutputStream(tarPath));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 关闭输入流
	 * @param in
	 */
	public static void closeSource(InputStream in){
		if(in!=null){
			try{
			in.close();
			}catch(Exception e){}
		}
	}
	/**
	 * 关闭输出流
	 * @param out
	 */
	public static void closeSource(OutputStream out){
		if(out!=null){
			try {
				out.close();
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
	/**
	 * 关闭输入流和输出流
	 * @param in
	 * @param out
	 */
	public static void closeSource(InputStream in,OutputStream out){
		closeSource(in);
		closeSource(out);
	}

	
	public static void main(String[] args) {
		String content="你好嘛\r\n哈哈哈";//以UTF-8来编码，默认一个汉字三个字节，加上文件的开头标志
		overrideToFile(content, "D://2.txt", "UTF-8");
		byte[] bytes=readInFile("D:/2.txt");
		for(int i=0;i<bytes.length;i++){
			System.out.print(bytes[i]+"\t");
		}
	}
}
